MODULE Inst30;

(*$R-, S-, P+, M- *) 

(* Modul:               DB-Conv                                 *)
(* Autor:               Dirk Steins                             *)
(* erstellt am:         15.2.93                                 *)
(* letzte Žnderung am:  16.02.93                                *)
(* Version:             0.11                                    *)
(* Interne Version:     V#002                                   *)
(* Kommentar:           Datenbankkonvertierer und Installations-*)
(*                      programm zu CAT 2.0                     *)


(*==============================================================*)
(* Datum    Version     Žnderung                                *)
(*==============================================================*)
(*                                                              *)
(* 15.2.93  0.1         Modul erstellt aus CatPutz, Konvert     *)
(*                      der Database geht. Es fehlt noch die    *)
(*                      Konvertierung der Zusatzdateien.        *)
(* 16.2.93  0.11        Konvertierung der GRUPPEN.POS eingebaut *)
(*                                                              *)
(*                                                              *)
(*==============================================================*)


FROM SYSTEM IMPORT ADDRESS, ADR, CADR, TSIZE, BYTE, ASSEMBLER, CALLSYS;

FROM MagicAES   IMPORT
     AESIntIn, AESAddrIn, AESIntOut,
     OBJECT, DISABLED, SELECTED, HIDETREE,
     GBUTTON, GSTRING,
     RED, MAGENTA, BLACK,
     MenuBar, MenuTnormal, MenuIenable,
     ShelEnvrn, FormAlert,
     EvntPmulti, EvntTimer, ObjcDraw,
     MNSELECTED, MUKEYBD, MUMESAG,
     KRSHIFT, KLSHIFT, KCTRL, KALT,
     WindUpdate, FormDial,
     ENDUPDATE, BEGUPDATE, FMDFINISH;
     
FROM MagicSys   IMPORT sBITSET, CastToInt, CastToBitset, Basepage;

FROM MagicXBIOS IMPORT Keytbl, Keycode, KEYTAB, PtrKEYTAB;

FROM MagicDOS    IMPORT Malloc, Mfree, Minus1;

FROM MagicTypes  IMPORT PtrPD;
     
        (* magic tools *)
FROM mtAppl     IMPORT
     ApplInit, ApplTerm, ApplIdent, VDIHandle, MaxWidth, MaxHeight,
     MouseArrow, ApplPath;
     
FROM mtDir      IMPORT  GetDir;

IMPORT MagicDOS, MagicAES;
     
(* mos *)
FROM Storage            IMPORT ALLOCATE, DEALLOCATE, Inconsistent;

FROM MOSGlobals         IMPORT PathStr, NameStr, FileStr;

FROM Lists      IMPORT  List,           CreateList,     DeleteList,
                        AppendEntry,    ListEmpty,      CurrentEntry,
                        NextEntry,      ResetList,      RemoveEntry,
                        ScanEntries,    LDir,           LCondProc,
                        NoOfEntries,    PrevEntry;

FROM TimeConvert IMPORT DateToText, TimeToText;

FROM Clock      IMPORT CurrentTime, CurrentDate;
(* strings *)

FROM Strings            IMPORT  String, Copy, Append, Empty, Space, Concat,
                                Assign, Length, Relation, Insert, Pos, StrEqual;

FROM FuncStrings        IMPORT  ConcStr;

FROM StrConv            IMPORT  LNumToStr, NumToStr, StrToCard, CardToStr;

IMPORT FastStrings, Block;

(* Disk I/O *)

FROM Directory          IMPORT  GetDefaultPath, SetDefaultPath, Delete, Rename;

FROM FileNames          IMPORT  ValidatePath, SplitPath, FileName;

IMPORT Files, Binary, Text;

        (* eigene Module *)
FROM InstRsc    IMPORT
     PtrObjTree, deskSize, menu, version, xVersion,
     InitResource, doInfo, 
     ClrRsrc, GetAndCreatePath, doConfig;
     
IMPORT Inst_30;

IMPORT Mintbind;

(* CAT-Module: *)

FROM Void   IMPORT v;

FROM GrafBase IMPORT Rectangle;

IMPORT CatFiles, dataSys;

 
  CONST  whatText  = '@(#) CAT-Install 3.0 V1.02 (c) 1996 Dirk Steins'+0c;


  CONST alt1    = "[3][Kann CAT30.DAT|nicht kopieren!][Abbruch]";  
        alt2    = "[3][Fehler beim Auspacken|von CAT30.ZFX!][Abbruch]";
        alt3    = "[3][Konnte CAT.INF nicht schliežen][OK]";
        alt4    = "[2][Install:|Willst Du CAT komplett neu|installieren oder ein Update|von CAT 2.x auf CAT 3.0|durchf�hren?][Neu|Update|Abbruch]";
        alt5    = "[1][Install:|Ohne Installationspfad|kann ich auch nix installieren!][Ach?!]";
        alt6    = "[1][Install:|Die Installation wurde|erfolgreich durchgef�hrt!][Hurra!]";
        
        newCat      = TRUE;
  
  TYPE  MaxStr    = ARRAY [0..255] OF CHAR;
        PtrMaxStr = POINTER TO MaxStr;
        
  VAR 
      newCatPath,
      dataBasePath,
      messagePath,
      targetPath,
      applpath        : FileStr;
      
      voidO     : BOOLEAN;
      voidC     : CARDINAL;
      voidI     : INTEGER;
      

PROCEDURE selectFile (REF title : ARRAY OF CHAR;
                      REF mask  : ARRAY OF CHAR;
                      VAR fName : ARRAY OF CHAR) : BOOLEAN;
  VAR void128 : PathStr;
      name    : NameStr;
      success : BOOLEAN;
BEGIN
  GetDefaultPath(targetPath);
  IF ~Empty (mask)
  THEN
    Append (mask, targetPath, voidO);
  ELSE
    Append ('*.*', targetPath, voidO);
  END;
  void128 := 0c;
  name := 0c;
  success := GetDir (targetPath, name, title);
  IF ~success THEN RETURN FALSE END;
  SplitPath(targetPath, targetPath, void128);
  ValidatePath (targetPath);
  SetDefaultPath (targetPath, voidI);
  Assign (ConcStr (targetPath, name), fName, voidO);
  RETURN TRUE
END selectFile;

PROCEDURE getFile (REF title : ARRAY OF CHAR;
                   VAR f : Files.File;
                   REF mask :ARRAY OF CHAR;
                   mode : Files.Access) : BOOLEAN;
  VAR fname   : String;
BEGIN
  MouseArrow;
  IF selectFile (title, mask, fname)
  THEN
    Files.Open (f, fname, mode);
    IF Files.State(f) < 0 THEN Files.ResetState (f); RETURN FALSE END;
    RETURN TRUE
  END;
  RETURN FALSE
END getFile;

PROCEDURE ConvMsgInfo();
CONST   msgInfoName = 'MSGINFO.DAT'+0C;

        (* Magics f�r Header *)
        msgCatMagic     = 4341544DH;  (* "CATM"                    *)
        msgVersion      = 2;          (* Versionsnummer der MsgManager.i *)
        oldVersionMagic = 0150H;      (* altes Versionsmagic             *)
        msgVersionMagic = 0160H;      (* Versionsmagic                   *)

TYPE
        shortInfo = RECORD 
                      msgType     : CARDINAL;
                      number      : INTEGER;
                      copyCount   : INTEGER;
                      refNum      : INTEGER;
                      sendMsg     : BOOLEAN;
                      toDelete    : BOOLEAN;
                      dist        : CARDINAL;
                      size        : LONGCARD;
                      noRefLine   : BOOLEAN;
                      cDate       : CARDINAL;
                      cTime       : CARDINAL;
                      (* Ab hier neu *)
                      orgDist     : CARDINAL;
                      reserved1,
                      reserved2   : LONGCARD; 
                    END;

        diskArrayPtr = POINTER TO ARRAY [0..999] OF shortInfo;

 VAR    msgHdl  : INTEGER;
        size    : LONGCARD;
        mess    : CARDINAL;
        shortArray : diskArrayPtr;
        i       : CARDINAL;
        dbHdr   : dataSys.FileHeaderType;
        fname   : MaxStr;
BEGIN
  (* MSGINFO.DAT einlesen, und pr�fen *)
  FastStrings.Assign (messagePath, fname);
  FastStrings.Append (msgInfoName, fname);
  msgHdl := MagicDOS.Fopen (fname, {MagicDOS.ReadWrite});
  IF msgHdl < 0       (* File not found *)
  THEN
    (* Nichts zum konvertieren da *)
    RETURN 
  ELSE
    CatFiles.Seek (0, msgHdl, CatFiles.end);
    size := CatFiles.FilePos (msgHdl);
    (* Erstmal den Header lesen und testen *)
    CatFiles.Seek (0, msgHdl, CatFiles.start);

    (* Jetzt erst mal Header einlesen *)
    CatFiles.Seek (0, msgHdl, CatFiles.start);
    CatFiles.ReadMuch (dataSys.dbHeaderLength, msgHdl, ADR(dbHdr));
    IF CatFiles.FileError # CatFiles.NoError
    THEN
      CatFiles.CloseFile (msgHdl);
      RETURN
    END;
    (* Jetzt �berpr�fen des Headers *)
    IF (dbHdr.CatMagic # msgCatMagic)
    OR (dbHdr.Version  # msgVersion)
    OR (dbHdr.VersionMagic # oldVersionMagic)
    THEN
      (* Entweder falsche oder nicht die alte Version,
       * nichts konvertieren
       *)
      CatFiles.CloseFile (msgHdl);
      RETURN
    END;
    
    mess := SHORT((size - dataSys.dbHeaderLength) DIV (TSIZE (shortInfo) - 10));
    ALLOCATE (shortArray, mess * TSIZE (shortInfo));
    IF shortArray = NIL THEN CatFiles.CloseFile (msgHdl); RETURN END;
    Block.Clear (shortArray, mess*TSIZE (shortInfo));
    (* Jetzt jedes Info einzeln einlesen und an die richtige Stelle setzen
     *)
    FOR i := 0 TO mess - 1 DO
      CatFiles.ReadMuch (TSIZE (shortInfo)-10, msgHdl, ADR(shortArray^[i]));
    END;
    (* Und jetzt den ganzen Kram mit neuer Versionsnummer rausschreiben *)
    dbHdr.CatMagic := msgCatMagic;
    dbHdr.Version  := msgVersion;
    dbHdr.VersionMagic := msgVersionMagic;
    CatFiles.Seek (0, msgHdl, CatFiles.start);
    CatFiles.WriteMuch (dataSys.dbHeaderLength, msgHdl, ADR(dbHdr));
    CatFiles.WriteMuch (LONG(mess) * TSIZE (shortInfo), msgHdl, shortArray);
    DEALLOCATE (shortArray, 0);
    CatFiles.CloseFile (msgHdl);
  END;    
END ConvMsgInfo;

PROCEDURE MemAvail () : LONGCARD;
BEGIN
  RETURN LONGCARD(Malloc (Minus1));
END MemAvail;

PROCEDURE copy (REF from, to : ARRAY OF CHAR; move: BOOLEAN; VAR res :INTEGER);
  VAR s, d : Files.File;
      mbuf : ADDRESS;
      slen : LONGCARD;
      blen : LONGCARD;
      pos  : LONGCARD;
      readB: LONGCARD;

  PROCEDURE closeIt();
  BEGIN
    voidO := Mfree (mbuf);
    Files.Close (d);
    Files.Close (s);
  END closeIt;
  
BEGIN
  Files.Open (s, from, Files.readOnly);
  IF Files.State(s) < 0
  THEN
    res := -1;
    RETURN;
  END;
  Files.Create (d, to, Files.writeOnly, Files.replaceOld);
  IF Files.State(d) < 0
  THEN
    res := -1;
    RETURN;
  END;
  slen := Binary.FileSize (s);
  blen := MemAvail();
  IF blen < 12000 THEN res := -39; RETURN END;
  blen := blen - 8192;
  mbuf := Malloc ( blen);
  IF mbuf = NIL THEN RETURN END;
  pos := 0L;
  WHILE pos + blen <= slen DO
    Binary.ReadBytes (s, mbuf, blen, readB);
    Binary.WriteBytes (d, mbuf, blen);
    INC (pos, blen);
  END;
  IF pos < slen THEN
    Binary.ReadBytes (s, mbuf, slen-pos, readB);
    Binary.WriteBytes (d, mbuf, slen-pos);
  END;
  closeIt;
  res := 0;
  IF move THEN Delete (from, res); END;
END copy;

PROCEDURE ExtractArchive(): BOOLEAN;
  CONST arcName = 'CAT30.DAT';
        expName = 'CAT30.ZFX';
        clrStr  = 33c+'E'+0c;
  VAR cmd, oName, nName : FileStr;
      res          : INTEGER;
BEGIN
  FastStrings.Assign (applpath, oName);
  FastStrings.Append (arcName, oName);
  FastStrings.Assign (newCatPath, nName);
  FastStrings.Append (expName, nName);
  IF StrEqual (applpath, newCatPath)
  THEN
    Rename (oName, nName, res);
  ELSE
    copy (oName, nName, FALSE, res);
  END;
  IF res # 0 THEN 
    v.int := MagicAES.FormAlert (1, alt1); 
    RETURN FALSE 
  END;
  (* Auf executable setzen f�r MiNT *)
  v.lint := Mintbind.Fchmod (nName, BITSET(0777H));
  cmd[0] := 0c;
  SetDefaultPath (newCatPath, voidI);
  MagicDOS.Cconws (clrStr);
  res := MagicDOS.Pexec(MagicDOS.LoadnGo, nName, cmd, cmd);
  IF res # 0 THEN 
    v.int := MagicAES.FormAlert (1, alt2); 
    RETURN FALSE 
  END;
  Delete (nName, res);
  RETURN TRUE;
END ExtractArchive;

CONST RscName = "INST_30.RSC";

PROCEDURE readCatInf (f : Files.File): BOOLEAN;
  VAR i : INTEGER;
BEGIN
  FOR i := 1 TO 7 DO
    Text.ReadLn (f);
  END;
  Text.ReadString (f, messagePath);
  Text.ReadLn (f);
  Text.ReadLn (f);
  Text.ReadLn (f);
  Text.ReadString (f, dataBasePath);
  Files.Close (f);
  IF Files.State (f) # 0 THEN i := MagicAES.FormAlert (1, alt3); END;
  SetDefaultPath (dataBasePath, voidI);
  MouseArrow();
  RETURN TRUE
END readCatInf;

PROCEDURE readNewInf (): BOOLEAN;
  VAR f : Files.File;
      oldDir: MaxStr;
BEGIN
 Assign (newCatPath, oldDir, voidO);
 IF ~getFile ('CAT.INF laden',f,'*.INF',Files.readSeqTxt)
 THEN
   RETURN FALSE
 END;
 (* Gruppenliste l”schen *)
 IF ~readCatInf (f)
 THEN
   RETURN FALSE
 END;
 RETURN TRUE;
END readNewInf;

PROCEDURE init(): BOOLEAN;
(* Lesen von CAT.INF
 * Zeile 11:    Database-Pfad
 *)
 VAR rscName : String;
BEGIN
  rscName := RscName;
  IF InitResource (rscName)
  THEN
    RETURN TRUE
  ELSE
    RETURN FALSE
  END;
END init;

VAR gruFile : Files.File;

VAR msgBuf : ARRAY [0..15] OF INTEGER;
    ende : BOOLEAN;
    but  : CARDINAL;
    event : sBITSET;

(*-------------- Menu Handling -----------------------------*)

VAR quitProg : BOOLEAN;

PROCEDURE menuManager (item, menuIndex : CARDINAL; kstate : BITSET);
  VAR res : INTEGER;
      instNew : BOOLEAN;
      name    : NameStr;
      path    : FileStr;
      r       : Rectangle;
BEGIN
  CASE item OF
    Fminsta  : (* Erstmal erfragen, ob CAT neu installiert werden soll
                * oder ob eine alte Datenbank �bernommen werden soll
                *)
               res := MagicAES.FormAlert (1, alt4);
               IF res = 3 THEN 
                 MenuTnormal (menu, menuIndex, 1);
                 RETURN
               END;
               instNew := res = 1;
               (* Jetzt den Installationspfad rausfinden *)
               FastStrings.Assign (applpath, path);
               
               IF ~GetAndCreatePath (path, name, 'Installationspfad')
               THEN
                 res := MagicAES.FormAlert (1, alt5);
                 MenuTnormal (menu, menuIndex, 1); 
                 RETURN
               END;
               (* Pfad ist nun vorhanden und steht in path *)
               FastStrings.Assign (path, newCatPath);
               
               IF ~instNew
               THEN
                 (* Jetzt erst CAT.INF lesen *)
                 IF ~readNewInf()
                 THEN
                   MenuTnormal (menu, menuIndex, 1);
                   RETURN
                 END;
               END;
                 
               (* So, jetzt erstmal CAT auspacken lassen *)
               IF ~ExtractArchive()
               THEN
                 MenuTnormal (menu, menuIndex, 1); 
                 RETURN
               ELSE
                 (* Redraw �ber gesamten Screen ausl”sen *)
                 WITH r DO
                   x := 0; y := 0; w := MaxWidth; h := MaxHeight;
                 END;
                 FormDial(FMDFINISH, r, r);
                 v.int := MenuBar(menu, MagicAES.Set);
                 WindUpdate (ENDUPDATE);
                 EvntTimer (100);
                 WindUpdate (BEGUPDATE);
                 
               END;

               (* Wenn nur installiert werden soll, dann sind wir fast fertig! *)
               IF instNew
               THEN
                 doConfig (newCatPath, dataBasePath); (* CAT.INF erstellen *)
               ELSE
                 (* MsgInfo.DAT konvertieren *)
                 ConvMsgInfo();
               END;
                 
               voidI := MagicAES.FormAlert (1, alt6);
               |
    Fmquit   : MenuTnormal (menu, menuIndex, 1); quitProg := TRUE; |
    Aboutobj : doInfo(); |
  ELSE
  END;
  MenuTnormal (menu, menuIndex, 1);
END menuManager;

PROCEDURE setMultiParam();
BEGIN
  AESIntIn[0] := CastToInt (sBITSET{MUMESAG});
  AESAddrIn[0] := ADR (msgBuf);
END setMultiParam;

VAR scan : CHAR;
    key  : CHAR;
    kstate : sBITSET;
    keyscan : INTEGER;

CONST AP_TERM = 50;
 
PROCEDURE getMultiResult();
BEGIN
  kstate := CastToBitset(AESIntOut[4]);
  keyscan := AESIntOut[5];
  (* Das auseinanderpfl�cken der einzeilnen Bytes geht in Assembler
   * einfacher als in M2
   *)
  ASSEMBLER
    MOVE.W      keyscan,D0      ; kreturn (ASCII und Scan)
    MOVE.B      D0,key          ; Ascii nach key (Bits 0..7)
    LSR.W       #8,D0           ; D0 rotieren
    MOVE.B      D0,scan         ; Scancode holen (Bits 8..15)
  END;
END getMultiResult;


BEGIN
  dataBasePath := whatText;     (* gegen optimierenden Linker *)
  ApplPath (applpath);
  IF ~init() THEN RETURN END;
  MouseArrow;
  voidI := MenuBar (menu, 1);
  quitProg := FALSE;
  LOOP
    setMultiParam();
    event := EvntPmulti ();
    getMultiResult();
    WindUpdate (BEGUPDATE);
    IF MUMESAG IN event
    THEN
      CASE msgBuf[0] OF
        MNSELECTED : menuManager (msgBuf[4], msgBuf[3], kstate); 
                     MouseArrow(); |
        AP_TERM    : quitProg := TRUE; |
      ELSE
      END
    END;
    WindUpdate (ENDUPDATE);
    IF quitProg THEN EXIT END;
  END;
  ClrRsrc();
  ApplTerm(0);
END Inst30.
